import string  
import random
import time
import global_objects as go

def normalize(min_value, max_value, digitsCount):

    """Normalizes the interval which is limited between min_value and max_value
    to interval where min_value is the smallest number with digitsCount digits
    and max_value is the biggest number with digitsCount digits"""
    
    if len(str(max_value)) > digitsCount:
        max_value = int('9'*digitsCount)
    if len(str(min_value))< digitsCount:
        min_value = int('1'+'0'*(digitsCount-1))
    return (min_value, max_value)

def genNumeric(arguments): #arguments= [number_of_digits='', precision='', min_value='', middle_value='', max_value='', divisibility='', key='', references='']

    """Generates numeric fields according to the specified arguments
    field_name : numeric (number_of_digits, precision, min_value,
    middle_value, max_value, divisibility, key, references)"""
   
    argumentsCnt = len(arguments)
    for i in range(argumentsCnt,8):
        arguments.append('')
       
    if (arguments[0] == '' and arguments[1]=='' and arguments[2]=='' and arguments[3]=='' and arguments[4]=='' and arguments[5]=='' and arguments[6]=='' and arguments[7]=='') or arguments==[]: #numeric,numeric()
        return dumbNumeric()

    if arguments[1] == '':
        precision = 0
    else:
        precision = int(arguments[1])

    if arguments[2] == '':
        min_value = 0
    else:
        min_value = int(arguments[2])
        
    if arguments[4] == '':
        max_value = 9999999999
    else:
        max_value = int(arguments[4]) 
        
    if arguments[5]=='':
        divisibility = 1
    else:
         divisibility = int(arguments[5])
         
    if arguments[0]=='':
        number_of_digits = len(str(max_value))
    else:
        number_of_digits = int(arguments[0])
        
    
    lFlag = False 
    key = arguments[6]
    left_side = random.randint(min_value, max_value)
    if (key=='p' or key=='P'):
        while(not lFlag):
            if (not left_side in go.pk) and left_side % divisibility == 0:
                lFlag = True
            else:
                left_side = random.randint(min_value, max_value)
        go.pk.append(left_side)
        return left_side
    else:
        mm = normalize(min_value, max_value, number_of_digits)    
        min_value = mm[0]
        max_value = mm[1]
        
        while(not lFlag):
            if len(str(left_side))== number_of_digits and left_side % divisibility == 0:
                lFlag = True
            else:
                left_side = random.randint(min_value, max_value)
            
    if precision > 0:
        right_side = random.randint(int('1'+'0'*(precision-1)), int('9'*precision))
        rFlag = False
        while(not rFlag):
            if right_side % divisibility == 0:
                rFlag = True
            else:
                right_side = random.randint(int('1'+'0'*(precision-1)), int('9'*precision))
        
        return str(left_side)+'.'+str(right_side)
    return left_side


def genDate():

    """Generates random date in specific range.
    field_name : date (format, start_date, end_date)"""

    return randomDate("19900101", "20100101", random.random())

def genString(arguments):

    """Generates a random strings with specified min_length, max_length, case and set of characters.
    field_name : sting (min_length, max_length, case, set_of_characters)
    """
    
    argumentsCnt = len(arguments)
    for i in range(argumentsCnt,4):
        arguments.append('')
        
    if arguments[0]=='' and arguments[1]=='' and arguments[2]=='' and arguments[3]=='':
        return dumbString()

    if arguments[0] == '':
        min_length = 0
    else:
        min_length = int(arguments[0])

    if arguments[1] == '':
        max_length = 10
    else:
        max_length = int(arguments[1])

    if arguments[2] == '':
        case = 'l'
    else:
        case = arguments[2].lower()

    number_of_chars = random.randint(min_length, max_length)
    
    if arguments[3]=='' or arguments[3] == '[]':
        set_of_characters = '[' + string.ascii_letters + string.digits + ']'        #asciiTableInRange(33, 126)
    else:
        set_of_characters = arguments[3]
        
    if case=='l':
        return ''.join([random.choice(set_of_characters[1:-1]) for i in range(number_of_chars)]).lower()
    if case=='u':
        return ''.join([random.choice(set_of_characters[1:-1]) for i in range(number_of_chars)]).upper()
                
        
def dumbString():

    """Generates a dumb strings which contains from 1 to 10 characters"""

    number_of_chars = random.randint(1,10)
    alphabetRange = string.ascii_letters + string.digits                            #asciiTableInRange(33, 126)
    return ''.join(random.sample(alphabetRange, number_of_chars))


def asciiTableInRange(min_acii_code, max_acii_code):

    """Creates a string of characters with ascii codes from min to max"""

    for i in range(min_acii_code, max_acii_code+1):
        go.ascii_table[i]= chr(i)
    return '['+''.join(go.ascii_table.values())+']'

def dumbNumeric():

    """Generates a dumb numeric, random integer which contains from 1 to 10 digits"""

    number_of_digits = random.randint(1,10)
    return int(random.random()*(10**number_of_digits))

def strTimeProp(start, end, format, prop):
    """Get a time at a proportion of a range of two formatted times.

    start and end should be strings specifying times formated in the
    given format (strftime-style), giving an interval [start, end].
    prop specifies how a proportion of the interval to be taken after
    start.  The returned time will be in the specified format.
    """

    stime = time.mktime(time.strptime(start, format))
    etime = time.mktime(time.strptime(end, format))

    ptime = stime + prop * (etime - stime)

    return time.strftime(format, time.localtime(ptime))


def randomDate(start, end, prop):
    return strTimeProp(start, end, '%Y%m%d', prop) 


